package presentation;

import java.awt.Color;
import java.awt.Font;
import java.text.DecimalFormat;
import java.util.Observable;
import java.util.Observer;

import org.jfree.chart.plot.dial.DialBackground;
import org.jfree.chart.plot.dial.DialCap;
import org.jfree.chart.plot.dial.DialPlot;
import org.jfree.chart.plot.dial.DialPointer;
import org.jfree.chart.plot.dial.DialTextAnnotation;
import org.jfree.chart.plot.dial.StandardDialFrame;
import org.jfree.chart.plot.dial.StandardDialScale;
import org.jfree.data.general.DefaultValueDataset;

import entity.EPatternRegister;
import entity.ERegister;

public class PRPMDial extends DialPlot  implements Observer {
	private static final long serialVersionUID = 1L;
	private DefaultValueDataset data;
	DialTextAnnotation gearValue;
	private enum Gears
	{
		firstgear, secondgear, thirdgear, fourthgear, fifthgear, sixthgear, neutral, nogear;
	    
	    public static Gears toDatatype(String datatype)
	    {
	        try {
	            return valueOf(datatype.toLowerCase());
	        } 
	        catch (Exception ex) {
	            return nogear;
	        }
	    }
	}
	
	public PRPMDial(double[] boundary) {
		if (boundary[0] == 0 && boundary[1] == 0) {
			boundary[0] = 0;
			boundary[1] = 15000;
		}
		
		Double steps = 3000.;
		
		/** The dataset. */
		data = new DefaultValueDataset(0);
		this.setDataset(data);
		
		// Dial title
		DialTextAnnotation title = new DialTextAnnotation("RPM");
        title.setAngle(90);
        title.setFont(new Font("Arial", Font.BOLD, 30));
        title.setRadius(0.50);
        title.setPaint(Color.lightGray);
        this.addLayer(title);
		
		// Marked ranges
		PDialRange yellowRange = new PDialRange(10000, 12000, Color.yellow);
        yellowRange.setInnerRadius(0.93);
        yellowRange.setOuterRadius(0.93);
        this.addLayer(yellowRange);
        
        PDialRange redRange = new PDialRange(12300, 14700, Color.red);
        redRange.setInnerRadius(0.93);
        redRange.setOuterRadius(0.93);
        this.addLayer(redRange);
		
        // Tickmarks and text
        StandardDialScale scale = new StandardDialScale(boundary[0], boundary[1], 210, -240, steps, 5);
        scale.setTickRadius(0.93);
        scale.setTickLabelOffset(0.25);
        scale.setTickLabelFont(new Font("Arial", Font.PLAIN, 14));
        scale.setTickLabelPaint(Color.black);
        scale.setTickLabelFormatter(new DecimalFormat("###"));
        this.addScale(0, scale);
        
        // Frame
        StandardDialFrame dialFrame = new StandardDialFrame();
        dialFrame.setBackgroundPaint(Color.lightGray);
        dialFrame.setForegroundPaint(Color.darkGray);
        this.setDialFrame(dialFrame);
        
        //Needle attachment
		DialCap cap = new DialCap();
        cap.setRadius(0.1);
        this.setCap(cap);
        
        // Neddle
        DialPointer needle = new DialPointer.Pointer();
        needle.setRadius(0.9);
        this.addLayer(needle);
        
        // Background
        this.setBackground(new DialBackground(Color.white));
        
        // Text on dial
        DialTextAnnotation gearLabel = new DialTextAnnotation("Gear:");
        gearLabel.setFont(new Font("Arial", Font.BOLD, 14));
        gearLabel.setRadius(0.32);
        this.addLayer(gearLabel);
        
        gearValue = new DialTextAnnotation("-");
        gearValue.setFont(new Font("Arial", Font.BOLD, 40));
        gearValue.setRadius(0.42);
        this.addLayer(gearValue);
	}
	
	private String getGear(String gear) {
		switch (Gears.toDatatype(gear.replace(" ", "").toLowerCase())) {
		case firstgear:
			return "1";
		case secondgear:
			return "2";
		case thirdgear:
			return "3";
		case fourthgear:
			return "4";
		case fifthgear:
			return "5";
		case sixthgear:
			return "6";
		case neutral:
			return "N";
		case nogear:
			return "-";
		default:
			return "-";
		}
	}
	
	@Override
	public void update(Observable obs, Object arg) {
		if (arg instanceof Number && obs instanceof ERegister) {
			if (((ERegister) obs).getName().equalsIgnoreCase("RPM")) {
				data.setValue((Number) arg);
			}
		} else if (arg instanceof String && obs instanceof EPatternRegister) {
			if (((ERegister) obs).getName().equalsIgnoreCase("Gear")) {
				String gear = ((EPatternRegister) obs).getTextValue();
				gearValue.setLabel(getGear(gear));
			}
		}
	}
}
